package test;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringReader;
import java.net.Socket;

public class SocketBase {

	public Socket socket;
	public BufferedReader in;
	public PrintWriter out;
	public static int FILE_READY = 2;
	public static int MESSAGE_READY = 1;
	public static int NOT_READY = 0;

	protected static String end = "eof" + SocketBase.class;
	protected static String close = "close" + SocketBase.class;
	protected static String startMessage = "start" + SocketBase.class;
	protected static String startFile = "startFile" + SocketBase.class;
	protected boolean debug = true;

	public SocketBase(Socket socket) throws IOException {
		this.socket = socket;
		this.out = new PrintWriter(socket.getOutputStream(), true);
		this.in = new BufferedReader(new InputStreamReader(socket
				.getInputStream()));
	}

	/**
	 * Waits for the handshaking signal to appear on the input stream.
	 * 
	 * @return
	 * <ul>
	 * <li>{@link #NOT_READY} if no handshake signal has been sent</li>
	 * <li>{@link #MESSAGE_READY} if a message is being sent</li>
	 * <li>{@link #FILE_READY} if a file is being sent</li>
	 * </ul>
	 */
	protected int ready() {
		try {
			String recieved = in.readLine();
			if (recieved == null) {
				return NOT_READY;
			} else if (recieved.equals(SocketBase.startMessage)) {
				return MESSAGE_READY;
			} else if (recieved.equals(SocketBase.startFile)) {
				return FILE_READY;
			} else {
				return NOT_READY;
			}
		} catch (IOException e) {
			return NOT_READY;
		}
	}

	protected String read() {
		String input;
		StringBuffer output = new StringBuffer();

		try {
			while ((input = in.readLine()) != null) {
				if (input.equals(SocketBase.end)) {
					break;
				}
				output.append(input);
			}
		} catch (IOException e) {
			System.err.println("IOException reading from socket on port:"
					+ socket.getPort());
		}
		return output.toString();

	}

	protected boolean write(String output) {
		BufferedReader reader = new BufferedReader(new StringReader(output));
		String temp;
		try {
			out.println(SocketBase.startMessage);
			while ((temp = reader.readLine()) != null) {
				out.println(temp);
			}
		} catch (IOException e) {
			return false;
		}
		out.println(SocketBase.end);
		return true;
	}

	protected boolean close() {
		try {
			getSocket().close();
			if(debug) {
				System.out.println("Client closed socket on port " + getSocket().getPort());
			}
			return true;
		} catch (IOException e) {
			return false;
		}
	}

	/**
	 * @return the socket
	 */
	protected Socket getSocket() {
		return socket;
	}

	/**
	 * @return the in
	 */
	protected BufferedReader getInReader() {
		return in;
	}

	/**
	 * @return the out
	 */
	protected PrintWriter getOutWriter() {
		return out;
	}

	protected boolean sendFile(File file) {
		if(debug) {
			System.out.println("Sending file " + file.getName());
		}
		try {
			BufferedReader reader = new BufferedReader(new FileReader(file));
			out.println(startFile);
			out.println(file.getName());
			String sent;
			while ((sent = reader.readLine()) != null) {
				out.println(sent);
			}
		} catch (IOException e) {
			if(debug) {
				System.err.println("Failed to send file " + file.getName());
			}
			return false;
		}
		out.println(end);
		if(debug) {
			System.out.println("Succesfully sent file " +  file.getName());
		}
		return true;
	}

	/**
	 * Receives a {@link File} being sent and writes it to the directory specified
	 * specified. Assumes that status flag has already been read.
	 * 
	 * @param dir
	 * @return true if {@link File} was successfully received, else false
	 * @see #ready()
	 */
	protected boolean receiveFile(File dir) {
		String fileName = "";
		File newFile = null;
		try {
			fileName = in.readLine();
			newFile = new File(dir + "\\" + fileName);
			BufferedWriter writer = new BufferedWriter(new FileWriter(newFile));
			String received = in.readLine();
			if(received == null) {
				return false;
			}
			if(debug) {
				System.out.println("Recieving " + fileName + "...");
			}
			while (!received.equals(SocketBase.end)) {
				writer.write(received);
				writer.newLine();
				received = in.readLine();
			}
			writer.close();
		} catch (IOException e) {
			if(debug) {
				System.err.println("Failed to recieve file " + fileName);
			}
			return false;
		}
		if(debug) {
			System.out.println("Successfully recieved file " + newFile.getAbsolutePath());
		}
		return true;
	}

}
